int ExtendedVerilogParser::readVerilogFile (CircuitGraph& graphIn, std::map <std::string, LibParserCellInfo>& sLib )
{

	cout << "Start reading verilog ..."<< endl ;
	
	string moduleName ;
	bool valid = (*this).read_module (moduleName) ;
	assert (valid) ;
	
	string& gn = boost::get_property(graphIn, boost::graph_name) ;
	gn = moduleName ;
	//cout << "Module " << boost::get_property(graphIn, boost::graph_name) << endl << endl ;
	
        this->gate_cnt = 0;
        
	this->readPrimaryInputs (graphIn) ;
	cout << "End reading primary inputs" << endl ;
	this->readPrimaryOutputs (graphIn) ;
	cout << "End reading primary outputs" << endl ;
	this->readWires (graphIn) ;
	cout << "End reading nets" << endl ;
	this->readCells (graphIn, sLib) ;
	cout << "End reading cells" << endl ;
        
	return 0 ;
	
}

inline bool ExtendedVerilogParser::extractIsInput (std::string pinName, std::vector<LibParserPinInfo>& libraryCell)
{
	vector<LibParserPinInfo>::iterator it ;
	
	for (it = libraryCell.begin() ; it != libraryCell.end() ; it++)
		if ((*it).name == pinName)
			return (*it).isInput ;
			
	return false ;
	
}

inline void ExtendedVerilogParser::fillListSameFootPrint (std::string footPrint, std::vector<std::string>& setCells, 
                                                          std::map <std::string, LibParserCellInfo>& sLib)
{
	std::map<std::string, LibParserCellInfo>::iterator it;
	
	for ( it = sLib.begin() ; it != sLib.end(); it++)
		if ( (*it).second.footprint ==  footPrint )
			setCells.push_back ((*it).second.name);
}

inline void ExtendedVerilogParser::extractFootPrint (std::string cellName, std::string& footPrint, std::map <std::string, LibParserCellInfo>& sLib)
{
	footPrint = sLib[cellName].footprint ;
}

inline bool ExtendedVerilogParser::extractIsSequential (std::string cellName, std::map <std::string, LibParserCellInfo>& sLib)
{
	return sLib[cellName].isSequential ;
}

void ExtendedVerilogParser::readPrimaryInputs (CircuitGraph& graphIn) 
{	
	bool valid ;	
	do {
		gateProperty tempGate ;	
		string primaryInput ;
		valid = (*this).read_primary_input (primaryInput) ;

		if (valid)
		{
			//cout << "Primary input: " << primaryInput << endl ;
			tempGate.footPrint = "PI" ;
			tempGate.instanceName = primaryInput ;
			tempGate.cellName = primaryInput ;
			tempGate.gateType = PrimaryInput ;
			tempGate.Slack_Violation = 0.0 ;
			tempGate.Slew_Violation = 0.0 ;
			tempGate.Cap_Violation = 0.0 ;
                        tempGate.visited = 0;
                        tempGate.gate_idx = this->gate_cnt;
                        this->gate_cnt++;

			// No list of cells
			tempGate.mapPinNetDirection["in"] = std::make_pair("in", Input);
			tempGate.mapPinNetDirection["out"] = std::make_pair("out", Output) ;
			
			vertex_descriptor newVertex = boost::add_vertex(tempGate, graphIn) ;
			this->instanceNodeMap[tempGate.instanceName] = newVertex;
			
			netConnectivity tmpNet ;
			
			tmpNet.netName = primaryInput ;
			tmpNet.sourceVertex = newVertex ;
			tmpNet.sourcePin = "out" ;
			
			this->verilogConnectivity.push_back(tmpNet) ;
		}
	
	} while (valid) ;
}


void ExtendedVerilogParser::readPrimaryOutputs (CircuitGraph& graphIn) 
{	
	bool valid ;
	do {
		gateProperty tempGate ;	
		string primaryOutput ;
		
		valid = (*this).read_primary_output (primaryOutput) ;
		if (valid)
		{
			//cout << "Primary output: " << primaryOutput << endl ;
			
			tempGate.footPrint = "PO" ;
			tempGate.instanceName = primaryOutput ;
			tempGate.cellName = primaryOutput ;
			tempGate.gateType = PrimaryOutput ;
                        tempGate.Slack_Violation = 0.0 ;
			tempGate.Slew_Violation = 0.0 ;
			tempGate.Cap_Violation = 0.0 ;
                        tempGate.visited = 0;
                        tempGate.gate_idx = this->gate_cnt;
                        this->gate_cnt++;

			// No list of cells
			tempGate.mapPinNetDirection["in"] = std::make_pair("in", Input);
			tempGate.mapPinNetDirection["out"] = std::make_pair("out", Output) ;
			
			vertex_descriptor newVertex = boost::add_vertex(tempGate, graphIn) ;
			this->instanceNodeMap[tempGate.instanceName] = newVertex;
			netConnectivity tmpNet ;
			tmpNet.netName = primaryOutput ;
			tmpNet.targetVertices.push_back(newVertex) ;
			tmpNet.targetPins.push_back("in") ;
			this->verilogConnectivity.push_back(tmpNet) ;
			
		}
	
	} while (valid) ;
}

void ExtendedVerilogParser::readWires (CircuitGraph& graphIn)
{
	bool valid ;
	do {
                string net ;
                valid = (*this).read_wire (net) ;
		vector<netConnectivity>::iterator it ;
		bool find = false ;
                if (valid)
                {
                        //cout << "Net: " << net << endl ;
      		
                        for (it = (this->verilogConnectivity).begin() ; it != (this->verilogConnectivity).end() ; it++)
                        {
                                if ((*it).netName == net)
                                        find = true ;
                        }

			if (!find)
			{
				netConnectivity tmpNet ;
				tmpNet.netName = net ;
				this->verilogConnectivity.push_back(tmpNet) ;
			}

                }

  	} while (valid) ;
}

void ExtendedVerilogParser::readCells (CircuitGraph& graphIn, std::map <std::string, LibParserCellInfo>& sLib)
{

	bool valid ;
	//cout << "Cell insts: " << endl ;
	vector<netConnectivity>::iterator it ;
	do {
	
                string cellType, cellInst ;
                gateProperty tempGate ;
                
                vector<std::pair<string, string> > pinNetPairs ;
    
                valid = this->read_cell_inst (cellType, cellInst, pinNetPairs) ;

                if (valid) {
                        
                        //cout << cellType << " " << cellInst << " " ;
                        
			extractFootPrint(cellType, tempGate.footPrint, sLib);
			tempGate.instanceName = cellInst;
			tempGate.cellName = cellType ;
			tempGate.gateType = (extractIsSequential(cellType, sLib)) ? Sequential : Combinational ;
                        tempGate.visited = 0;
                        tempGate.Slack_Violation = 0.0 ;
                        tempGate.isFixed = false ;
			tempGate.Slew_Violation = 0.0 ;
			tempGate.Cap_Violation = 0.0 ;
			
			tempGate.minDelayLeakage = 1000000000.0 ;
			tempGate.maxDelayLeakage = 0.0 ;
			
			tempGate.minDelayAvg = 100000000.0 ;
			tempGate.maxDelayAvg = 0.0 ;

                        tempGate.gate_idx = this->gate_cnt;
                        this->gate_cnt++;

			fillListSameFootPrint (tempGate.footPrint, tempGate.listOfCells, sLib);
			bool isInput = false ;
			
                        for (int i=0; i < (int)pinNetPairs.size(); ++i) {
                                isInput = extractIsInput( pinNetPairs[i].first, sLib[cellType].pins) ;
                                tempGate.mapPinNetDirection[pinNetPairs[i].first] = make_pair (pinNetPairs[i].second, 
                                                                                               (isInput) ? Input : Output) ;
      									

                                //cout << "(" << pinNetPairs[i].first << " " << pinNetPairs[i].second << ") " ;
                        }
			
			vertex_descriptor newVertex = boost::add_vertex(tempGate, graphIn) ;
			this->instanceNodeMap[tempGate.instanceName] = newVertex;
			// add this vertex to vector
			if (tempGate.gateType == Combinational)
			{
				NodeSlackStruct		tmpNodeSlack ;
				tmpNodeSlack.vertexDescriptor = newVertex ;
				tmpNodeSlack.negativeSlack = 0.0 ;
				
				graphIn.nodeSlackVector.push_back(tmpNodeSlack) ;
			}
			//---------------------------------------------
			
			// update netConnectivity
			for (int i = 0 ; i < (int)pinNetPairs.size(); ++i) {
				isInput = extractIsInput( pinNetPairs[i].first, sLib[cellType].pins) ;
				
				for (it = this->verilogConnectivity.begin() ; it != this->verilogConnectivity.end() ; it++)
                                {
                                        if ((*it).netName == pinNetPairs[i].second)
                                        {
                                                if (isInput)
                                                {
                                                        (*it).targetVertices.push_back(newVertex) ;
                                                        (*it).targetPins.push_back(pinNetPairs[i].first) ;
                                                }
                                                else
                                                {
                                                        (*it).sourceVertex = newVertex ;
                                                        (*it).sourcePin = pinNetPairs[i].first ;
                                                }
                                        }
      					
                                }
			}
			
                        //cout << endl ;
                }
    
  	} while (valid) ;
  
}

netConnectivity ExtendedVerilogParser::getConnectivity(int index) const
{
	return this->verilogConnectivity[index] ;
}


void ExtendedVerilogParser::printNetConnectivity (CircuitGraph& graphIn)
{
	std::vector<netConnectivity>::iterator it ;
	std::vector<vertex_descriptor>::iterator vit ;
	
	
	cout << "Start printing connectivity..." << endl ;
	for (it = this->verilogConnectivity.begin() ; it != this->verilogConnectivity.end(); it++)
	{
		cout << "Name: " << (*it).netName << endl ;
		cout << "Connectivities: " << endl ;
		cout << endl << endl ;
		for (vit = (*it).targetVertices.begin() ; vit != (*it).targetVertices.end() ; vit++)
		{
			cout << "Source: " << graphIn[(*it).sourceVertex].instanceName << "=>" 
                             << graphIn[(*vit)].instanceName << endl ;
		}
		
		cout << endl << endl ;
	}
	
	cout << "end of printing connectivity" << endl ;
}


















